﻿@page "/blue-tooth"
@inject IStringLocalizer<Bluetooth> Localizer

<h3>@Localizer["BluetoothTitle"]</h3>

<h4>@Localizer["BluetoothIntro"]</h4>

<p>@((MarkupString)Localizer["BluetoothDescription"].Value)</p>

<Pre>[Inject, NotNull]
private IBluetooth? BluetoothService { get; set; }</Pre>

<Tips>
    <ul class="ul-demo">
        <li>@((MarkupString)Localizer["BluetoothTipsLi1"].Value)</li>
        <li>@((MarkupString)Localizer["BluetoothTipsLi2"].Value)</li>
    </ul>
    <div>@((MarkupString)Localizer["BluetoothTipsTitle"].Value)</div>
</Tips>

<DemoBlock Title="@Localizer["BaseUsageTitle"]"
           Introduction="@Localizer["BaseUsageIntro"]"
           Name="Normal">
    <section ignore>
        @Localizer["UsageDesc"]
    </section>
    <div class="row form-inline g-3">
        <div class="col-12">
            <Button Text="@Localizer["BluetoothRequestText"]" Icon="fa-brands fa-bluetooth" OnClick="RequestDevice"></Button>
            <Button Text="@Localizer["BluetoothConnectText"]" Icon="fa-solid fa-circle-play" IsAsync="true" IsDisabled="@(_blueDevice is not {Connected: false})" IsKeepDisabled="true" OnClick="Connect" class="ms-3"></Button>
            <Button Text="@Localizer["BluetoothDisconnectText"]" Icon="fa-solid fa-circle-stop" IsDisabled="@(_blueDevice is not {Connected: true})" OnClick="Disconnect" class="ms-3"></Button>
        </div>
        <div class="col-12">
            <Display Value="@BluetoothDeviceName" ShowLabel="true" DisplayText="Device Name"></Display>
        </div>
        <div class="col-12">
            <div class="d-flex align-items-center">
                <Button Text="@Localizer["BluetoothGetBatteryText"]" Icon="fa-solid fa-battery-half" IsDisabled="@(_blueDevice is not { Connected: true })" OnClick="GetBatteryValue"></Button>
                <label class="d-flex align-items-center"><progress value="@_batteryValue" max="100" class="ms-3"></progress><span class="ms-3">@_batteryValueString</span></label>
            </div>
        </div>
        <div class="col-12">
            <div class="d-flex align-items-center">
                <Button Text="@Localizer["BluetoothGetCurrentTimeText"]" Icon="fa-solid fa-clock" IsDisabled="@(_blueDevice is not { Connected: true })" OnClick="GetTimeValue"></Button>
                <label class="ms-3">@_currentTimeValueString</label>
            </div>
        </div>
        <div class="col-12">
            <div class="d-flex align-items-center">
                <Button Text="@Localizer["BluetoothDeviceInfoText"]" Icon="fa-solid fa-microchip" IsDisabled="@(_blueDevice is not { Connected: true })" OnClick="GetDeviceInfoValue"></Button>
            </div>
        </div>
        <div class="col-12">
            <div>
                @foreach (var info in _deviceInfoList)
                {
                    <div>@info</div>
                }
            </div>
        </div>
        <div class="col-12">
            <Button Text="@Localizer["BluetoothGetServicesText"]" Icon="fa-solid fa-server" IsDisabled="@(_blueDevice is not { Connected: true })" OnClick="GetServices"></Button>
        </div>
        <div class="col-12">
            <Select Items="ServicesList" @bind-Value="_selectedService" class="flex-fill"></Select>
        </div>
        <div class="col-12">
            <Button Text="@Localizer["BluetoothGetCharacteristicsText"]" Icon="fa-solid fa-plug" IsDisabled="@(_blueDevice is not { Connected: true })" OnClick="GetCharacteristics"></Button>
        </div>
        <div class="col-12">
            <Select Items="CharacteristicsList" @bind-Value="_selectedCharacteristic" class="flex-fill"></Select>
        </div>
        <div class="col-12">
            <Button Text="@Localizer["BluetoothReadValueText"]" Icon="fa-solid fa-memory" IsDisabled="@(_blueDevice is not { Connected: true })" OnClick="ReadValue"></Button>
        </div>
        <div class="col-12">
            <Textarea Value="@_readValueString" rows="3" readonly></Textarea>
        </div>
        <div class="col-12">
            <Button Text="@Localizer["BluetoothStartText"]" Icon="fa-solid fa-play" IsDisabled="@(_blueDevice is not { Connected: true })" OnClick="StartNotifications"></Button>
        </div>
        <div class="col-12">
            <Button Text="@Localizer["BluetoothStopText"]" Icon="fa-solid fa-stop" IsDisabled="@(_blueDevice is not { Connected: true })" OnClick="StopNotifications"></Button>
        </div>
    </div>
</DemoBlock>

<p class="code-label mt-3">1. 服务注入</p>

<Pre>[Inject]
[NotNull]
private IBluetooth? BluetoothService { get; set; }</Pre>

<p class="code-label">2. 列出蓝牙设备</p>
<p>调用 <code>BluetoothService</code> 实例方法 <code>RequestDevice</code> 即可，通过 <code>IsSupport</code> 进行浏览器是否支持蓝牙。可以通过 <code>BluetoothRequestOptions</code> 过滤参数过滤蓝牙设备</p>

<Pre>_serialPort = await BluetoothService.RequestDevice();
if (BluetoothService.IsSupport == false)
{
    await ToastService.Error(Localizer["NotSupportBluetoothTitle"], Localizer["NotSupportBluetoothContent"]);
}</Pre>

<p class="code-label">3. 连接设备</p>
<p>调用 <code>IBluetoothDevice</code> 实例方法 <code>Connect</code> 即可</p>

<Pre>private async Task Connect()
{
    if (_blueDevice != null)
    {
        var ret = await _blueDevice.Connect();
        if (ret == false && !string.IsNullOrEmpty(_blueDevice.ErrorMessage))
        {
            await ToastService.Error("Connect", _blueDevice.ErrorMessage);
        }
    }
}</Pre>

<p class="code-label">4. 断开设备</p>

<p>调用 <code>IBluetoothDevice</code> 实例方法 <code>Disconnect</code> 断开连接，请注意路由切换时，请调用其 <code>DisposeAsync</code> 方法释放资源</p>

<Pre>private async Task Disconnect()
{
    if (_blueDevice != null)
    {
        var ret = await _blueDevice.Disconnect();
        if (ret == false && !string.IsNullOrEmpty(_blueDevice.ErrorMessage))
        {
            await ToastService.Error("Disconnect", _blueDevice.ErrorMessage);
        }
    }
}</Pre>

<p class="code-label">注意事项</p>
<p>可以通过调用 <code>IBluetoothService</code> 实例方法 <code>GetAvailability</code> 方法后，判断其实例属性 <code>IsAvailable</code> 检查当前终端是否有蓝牙模块</p>

<p><code>IBluetoothService</code> 实例属性 <code>IsSupport</code> 是表示当前浏览器是否支持蓝牙功能</p>

<p><code>IBluetooth</code> 与 <code>IBluetoothDevice</code> 所有实例方法均有返回值，可通过查看其实例属性 <code>ErrorMessage</code> 获得上一次执行的错误描述信息</p>

<p><code>IBluetoothDevice</code> 实例方法 <code>ReadValue</code> 是通用方法，通过参数指定<code>ServiceUUID</code> 与 <code>CharacteristicUUID</code></p>

<p>原生方法 <code>getDevices</code> 暂未封装，因为需要设置浏览器才能开启</p>

<p>可根据自己的业务需求自定义扩展方法，内置方法列表如下：</p>

<ul class="ul-demo">
    <li><code>GetDeviceInfo</code> 读取设备信息</li>
    <li><code>GetCurrentTime</code> 读取当前时间</li>
    <li><code>GetBatteryValue</code> 读取电量方法</li>
</ul>

<p class="code-label">接口说明</p>
<ul class="ul-demo">
    <li><code>IBluetooth</code> 蓝牙服务（系统注入）</li>
    <li><code>IBluetoothDevice</code> 蓝牙设备</li>
    <li><code>IBluetoothService</code> 蓝牙设备提供的服务接口 如时间服务</li>
    <li><code>IBluetoothCharacteristic</code> 蓝牙设备服务提供的特性接口 如时间服务的当前时间特性（还有时区特性）</li>
</ul>

<p class="code-label">相关文档</p>

<ul class="ul-demo">
    <li>Service List：<a href="https://github.com/WebBluetoothCG/registries/blob/master/gatt_assigned_services.txt" target="_blank">[传送门]</a></li>
    <li>Characteristics List：<a href="https://github.com/WebBluetoothCG/registries/blob/master/gatt_assigned_characteristics.txt" target="_blank">[传送门]</a></li>
    <li>Descriptors List：<a href="https://github.com/WebBluetoothCG/registries/blob/master/gatt_assigned_descriptors.txt" target="_blank">[传送门]</a></li>
</ul>
